﻿using SnmpSharpNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace snmp测试
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.cmb协议.SelectedIndex = 0; //协议协议ver1
        }

        private void btn取所有节点值_Click(object sender, EventArgs e)
        {
            //取所有oid列表的数据
            try
            {
                string[] t = this.txtOID列表.Text.Split('\n');
                Dictionary<string, string> dict = new Dictionary<string, string>();
                foreach (string str in t)
                {
                    dict[str.Trim()] = "";
                }
                string err = snmpget(this.txt主机.Text.Trim(), this.txt团体.Text.Trim(), (SnmpVersion)(this.cmb协议.SelectedIndex), dict);
                if (err != "")
                    throw new Exception(err);
                DataTable dt = new DataTable();
                dt.Columns.Add("oid");
                dt.Columns.Add("val");
                foreach (var v in dict)
                {
                    dt.Rows.Add(v.Key, v.Value);
                }
                this.dg节点值.DataSource = dt.DefaultView;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void 取子节点值_Click(object sender, EventArgs e)
        {
            //输入一个oid，取此oid下级所有节点
            try
            {
                string[] t = this.txtOID列表.Text.Split('\n');
                Dictionary<string, string> dict = new Dictionary<string, string>();
                string err = snmpget子节点(this.txt主机.Text.Trim(), this.txt团体.Text.Trim(), (SnmpVersion)(this.cmb协议.SelectedIndex),t[0], dict);
                if (err != "")
                    throw new Exception(err);
                DataTable dt = new DataTable();
                dt.Columns.Add("oid");
                dt.Columns.Add("val");
                foreach (var v in dict)
                {
                    dt.Rows.Add(v.Key, v.Value);
                }
                this.dg节点值.DataSource = dt.DefaultView;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private string snmpget(string ipaddress, string comname, SnmpVersion ver, Dictionary<string, string> dict_oid)
        {
            // SNMP community name
            OctetString community = new OctetString(comname);
            AgentParameters param = new AgentParameters(ver, community);
            UdpTarget target = new UdpTarget(IPAddress.Parse(ipaddress), 161, 2000, 2);
            Pdu pdu = new Pdu(PduType.Get);
            foreach (string p in dict_oid.Keys)
            {
                string t = p.Trim();
                if (t != "")
                    pdu.VbList.Add(t);
            }


            SnmpPacket result = target.Request(pdu, param);
            // SnmpV2Packet result = (SnmpV2Packet);
            try
            {
                // If result is null then agent didn't reply or we couldn't parse the reply.
                if (result != null)
                {

                    if (result.Pdu.ErrorStatus != 0)
                    {
                        return $"ErrorStatus：{result.Pdu.ErrorStatus},ErrorIndex: { result.Pdu.ErrorIndex}";
                    }
                    else
                    {
                        dict_oid.Clear();
                        for (int m = 0; m < result.Pdu.VbCount; m++)
                        {
                            string id = result.Pdu.VbList[m].Oid.ToString();
                            dict_oid[id] = result.Pdu.VbList[m].Value.ToString();

                        }
                        return ""; //成功

                    }
                }
                else
                {
                    return "未收到数据";
                }
            }
            finally
            {
                target.Close();
            }
        }

        private string snmpget子节点(string ipaddress, string comname, SnmpVersion ver, string oid父, Dictionary<string, string> dict_oid)
        {
            //官方文档：http://snmpsharpnet.com/index.php/walk-operation-with-snmp-version-1-and-2c/
            //只适用于Ver2
            OctetString community = new OctetString(comname);
            AgentParameters param = new AgentParameters(ver, community);
            UdpTarget target = new UdpTarget(IPAddress.Parse(ipaddress), 161, 2000, 2);

            Oid rootOid = new Oid(oid父.Trim());
            Oid lastOid = (Oid)rootOid.Clone();

            Pdu pdu = new Pdu(PduType.GetBulk);
            pdu.NonRepeaters = 0;
            pdu.MaxRepetitions = 100;

            while (lastOid != null)
            {
                if (pdu.RequestId != 0)
                {
                    pdu.RequestId += 1;
                }

                pdu.VbList.Clear();
                pdu.VbList.Add(lastOid);
                SnmpPacket result = target.Request(pdu, param);
                if (result != null)
                {
                    if (result.Pdu.ErrorStatus == 0)
                    {
                        //dict_oid.Clear();
                        foreach (Vb v in result.Pdu.VbList)
                        {
                            //dict_oid[v.Oid.ToString()] = v.Value.ToString();
                            if (rootOid.IsRootOf(v.Oid))
                            {
                                dict_oid[v.Oid.ToString()] = v.Value.ToString();


                                if (v.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW)
                                    lastOid = null;
                                else
                                    lastOid = v.Oid;
                            }
                            else
                            {
                                lastOid = null;
                            }
                        }

                    }
                }
                else
                {
                    return "未收到数据";
                }
            }
            return "";
        }

    }
}
